/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		ntds ldap lookup guid.cpp
 * PURPOSE:		NTDS over LDAP support
 *				trustee SID lookup functions
 */

namespace Ldap
{

using namespace Lookup;
using namespace WorkQueue;

struct NtdsLookupTrusteeSidWorkItem : LookupWorkItem<WCHAR>
{
	auto_refct<LdapConnection> Lc;
	auto_szpod<WCHAR> Text;
	ULONG Op;

	NtdsLookupTrusteeSidWorkItem(CompletionTarget<WCHAR> *Ct, LdapConnection *Lc, SID const *Sid) :
		LookupWorkItem(Ct),
		Lc(Lc)
	{
		WCHAR SidText[MAX_SID_BYTES * 3]; //at most 3 escaped chars per each byte
		PWSTR Attrs[] = {L"distinguishedName", NULL};

		RaiseOnLdapError(ldap_escape_filter_element(c_cast<PCHAR>(Sid), GetSidLength(Sid), SidText, sizeof SidText));

		Op = StartLdapSearch(Lc, LDAP_SCOPE_SUBTREE, Attrs, NULL, SbtDomain, L"objectSid=%1$s", SidText);
	}

	virtual void Work() override
	{
		Result = AwaitSingleSearchResult<WCHAR>(Lc, Op, L"distinguishedName");
		Op = 0;
		if(!Result)
			RaiseNtError(STATUS_NONE_MAPPED);
	}

	~NtdsLookupTrusteeSidWorkItem()
	{
		if(Op)
			ldap_abandon(Lc->ld, Op);
	}
};

struct NtdsLookupTrusteeNameWorkItem : LookupWorkItem<SID>
{
	auto_refct<LdapConnection> Lc;
	ULONG Dn;
	ULONG Op;

	NtdsLookupTrusteeNameWorkItem(CompletionTarget<SID> *Ct, LdapConnection *Lc, PCWSTR Name) :
		LookupWorkItem(Ct),
		Lc(Lc)
	{
		PWSTR Attrs[] = {L"objectSid", NULL};

		Op = StartLdapSearch(Lc, LDAP_SCOPE_SUBTREE, Attrs, NULL, SbtDomain, L"(|(userPrincipalName=%1$s)(distinguishedName=%1$s)(anr=%1$s))", Name);
	}

	virtual void Work() override
	{
		Result = AwaitSingleSearchResult<SID>(Lc, Op, L"objectSid");
		Op = 0;
		if(!Result)
			RaiseNtError(STATUS_NONE_MAPPED);
	}

	~NtdsLookupTrusteeNameWorkItem()
	{
		if(Op)
			ldap_abandon(Lc->ld, Op);
	}
};

struct SidTranslator : Lookup::Translator<SID>
{
	auto_refct<LdapConnection> Lc;

	SidTranslator(LdapConnection *Lc) :
		Lc(Lc)
	{}
	SidTranslator(SDE_GENERIC_OPTS const &GenOpts, CHAR Privileges) :
		Lc(new LdapConnection(Lc->Module, GenOpts, Privileges))
	{}
	void LookupData(CompletionTarget<WCHAR> *Ct, SID const *Sid)
	{
		PostWorkItem(new NtdsLookupTrusteeSidWorkItem(Ct, Lc, Sid));
	}
	void LookupName(CompletionTarget<SID> *Ct, PCWSTR Name)
	{
		PostWorkItem(new NtdsLookupTrusteeNameWorkItem(Ct, Lc, Name));
	}
};

}//namespace Ldap